{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "aBj_0vRigiH7"
      },
      "source": [
        "# ChatGPT Inline Tips with simpleaichat\n",
        "\n",
        "[simpleaichat](https://github.com/minimaxir/simpleaichat) allows the user more control over text inputs and output. One way to do it is to analyze user input for potential issues, and display a warning if there are unexpected issues with the input.\n",
        "\n",
        "Inspired by Simon Willison's blog post [ChatGPT should include inline tips\n",
        "](https://simonwillison.net/2023/May/30/chatgpt-inline-tips/).\n",
        "\n",
        "**DISCLAIMER: This is far from a perfect solution, but a good proof-of-concept on how to use simpleaichat to address complex problems.**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "id": "kqL3etKLgiH9"
      },
      "outputs": [],
      "source": [
        "!pip install -q simpleaichat\n",
        "\n",
        "from simpleaichat import AIChat\n",
        "from rich.console import Console\n",
        "from getpass import getpass\n",
        "import time"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "For the following cell, input your OpenAI API key when prompted. **It will not be saved to the notebook.**."
      ],
      "metadata": {
        "id": "zld11X3xgr1O"
      }
    },
    {
      "cell_type": "code",
      "source": [
        "api_key = getpass(\"OpenAI Key: \")"
      ],
      "metadata": {
        "id": "xueo1SmCg2SF",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "92589df7-05d7-4d28-a163-acd805dbdb9a"
      },
      "execution_count": 2,
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "OpenAI Key: ··········\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "Let's create an AI chat, and a Console for output to the notebook."
      ],
      "metadata": {
        "id": "2O_1CUGVg8Y4"
      }
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "d4o0elPQgiH-"
      },
      "outputs": [],
      "source": [
        "ai = AIChat(api_key=api_key, console=False, params={\"temperature\": 0.0})  # for reproducibility\n",
        "console = Console(width=60, highlight=False)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xAPziFs-giH-"
      },
      "source": [
        "First, we'll set a list of rules that we can display. These rules are adapted from real-world incidents and OpenAI's [usage policies](https://openai.com/policies/usage-policies)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "id": "RLzlzbBrgiH-"
      },
      "outputs": [],
      "source": [
        "tips = [\n",
        "    \"This ChatGPT model does not have access to the internet, and its training data cut-off is September 2021.\",\n",
        "    \"ChatGPT should not be relied on for legal research of this nature, because it is very likely to invent realistic cases that do not exist.\",\n",
        "    \"Medical and psychatric advice from ChatGPT should not be relied upon. Always consult a doctor.\",\n",
        "    \"Tailored financial advice from ChatGPT should not be relied upon. Always consult a professional.\",\n",
        "    \"ChatGPT is not liable for any illegal activies committed as the result of its responses.\"\n",
        "]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b6q0JBoGgiH_"
      },
      "source": [
        "When generating a response from ChatGPT, we'll first check the user input against a bespoke function in a different context to see if ChatGPT can detect one of the issues above. This is accomplished through a system prompt, and forcing the model to choose a number between `1` and `5`, or `0` if nothing is present.\n",
        "\n",
        "The order of the tips above matches the order of the list. This is incidentially the same workflow as tools in simpleaichat."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "-C2Rp02igiH_"
      },
      "outputs": [],
      "source": [
        "tips_prompt = \"\"\"From the list of topics below, reply ONLY with the number appropriate for describing the topic of the user's message. If none are, ONLY reply with \"0\".\n",
        "\n",
        "1. Content after September 2021\n",
        "2. Legal/Judicial Research\n",
        "3. Medical/Psychatric Advice\n",
        "4. Financial Advice\n",
        "5. Illegal/Unethical Activies\"\"\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "id": "HzLh4Q6JgiH_"
      },
      "outputs": [],
      "source": [
        "# ensures tips output will always be an integer between 0 and 5 inclusive\n",
        "params = {\n",
        "    \"temperature\": 0.0,\n",
        "    \"max_tokens\": 1,\n",
        "    \"logit_bias\": {str(k): 100 for k in range(15, 15 + len(tips) + 1)}\n",
        "}\n",
        "\n",
        "# functional\n",
        "ai.new_session(id=\"tips\",\n",
        "               api_key=api_key,\n",
        "               system=tips_prompt,\n",
        "               save_messages=False,\n",
        "               params=params)\n",
        "\n",
        "def check_user_input(message):\n",
        "    tip_idx = ai(message, id=\"tips\")\n",
        "    if tip_idx == \"0\":  # no tip needed\n",
        "        return\n",
        "    else:\n",
        "        tip = tips[int(tip_idx) - 1]\n",
        "        console.print(f\"⚠️ {tip}\", style=\"bold\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5raNhn8igiIA"
      },
      "source": [
        "Let's test it in a conversation!"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "scrolled": false,
        "id": "DP3z0wIWgiIA",
        "outputId": "070fcfa9-016a-4abe-f15b-a094f525c4a2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        }
      },
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mYou:\u001b[0m "
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">You:</span> </pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Can you tell me more about Max v. Woolf?\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m⚠️ ChatGPT should not be relied on for legal research of this\u001b[0m\n",
              "\u001b[1mnature, because it is very likely to invent realistic cases \u001b[0m\n",
              "\u001b[1mthat do not exist.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">⚠️ ChatGPT should not be relied on for legal research of this</span>\n",
              "<span style=\"font-weight: bold\">nature, because it is very likely to invent realistic cases </span>\n",
              "<span style=\"font-weight: bold\">that do not exist.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1;95mChatGPT\u001b[0m\u001b[95m: Max v. Woolf is a legal case that took place in the\u001b[0m\n",
              "\u001b[95mUnited Kingdom in 2017. It involved a dispute between two \u001b[0m\n",
              "\u001b[95mauthors, Max and Woolf, over the alleged plagiarism of Max's\u001b[0m\n",
              "\u001b[95mwork by Woolf. Max claimed that Woolf had copied significant\u001b[0m\n",
              "\u001b[95mportions of his book without permission or attribution.\u001b[0m\n",
              "\n",
              "\u001b[95mThe case was heard in the High Court of Justice in London, \u001b[0m\n",
              "\u001b[95mwhere Max presented evidence of the similarities between his\u001b[0m\n",
              "\u001b[95mwork and Woolf's. Woolf denied the allegations and argued \u001b[0m\n",
              "\u001b[95mthat any similarities were coincidental or the result of \u001b[0m\n",
              "\u001b[95mcommon themes in the genre.\u001b[0m\n",
              "\n",
              "\u001b[95mAfter a lengthy trial, the judge ruled in favor of Max, \u001b[0m\n",
              "\u001b[95mfinding that Woolf had indeed plagiarized his work. Woolf \u001b[0m\n",
              "\u001b[95mwas ordered to pay damages to Max and to publicly \u001b[0m\n",
              "\u001b[95macknowledge the plagiarism.\u001b[0m\n",
              "\n",
              "\u001b[95mThe case received significant media attention and sparked a \u001b[0m\n",
              "\u001b[95mwider discussion about the issue of plagiarism in the \u001b[0m\n",
              "\u001b[95mpublishing industry. It also highlighted the importance of \u001b[0m\n",
              "\u001b[95mproper attribution and respect for intellectual property \u001b[0m\n",
              "\u001b[95mrights.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">ChatGPT</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">: Max v. Woolf is a legal case that took place in the</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">United Kingdom in 2017. It involved a dispute between two </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">authors, Max and Woolf, over the alleged plagiarism of Max's</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">work by Woolf. Max claimed that Woolf had copied significant</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">portions of his book without permission or attribution.</span>\n",
              "\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">The case was heard in the High Court of Justice in London, </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">where Max presented evidence of the similarities between his</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">work and Woolf's. Woolf denied the allegations and argued </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">that any similarities were coincidental or the result of </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">common themes in the genre.</span>\n",
              "\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">After a lengthy trial, the judge ruled in favor of Max, </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">finding that Woolf had indeed plagiarized his work. Woolf </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">was ordered to pay damages to Max and to publicly </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">acknowledge the plagiarism.</span>\n",
              "\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">The case received significant media attention and sparked a </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">wider discussion about the issue of plagiarism in the </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">publishing industry. It also highlighted the importance of </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">proper attribution and respect for intellectual property </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">rights.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mYou:\u001b[0m "
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">You:</span> </pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Everyone's talking about it on Twitter!\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m⚠️ This ChatGPT model does not have access to the internet, \u001b[0m\n",
              "\u001b[1mand its training data cut-off is September 2021.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">⚠️ This ChatGPT model does not have access to the internet, </span>\n",
              "<span style=\"font-weight: bold\">and its training data cut-off is September 2021.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1;95mChatGPT\u001b[0m\u001b[95m: It's not surprising that the case is generating a \u001b[0m\n",
              "\u001b[95mlot of discussion on social media platforms like Twitter. \u001b[0m\n",
              "\u001b[95mPlagiarism is a serious issue in the creative industries, \u001b[0m\n",
              "\u001b[95mand cases like Max v. Woolf can have far-reaching \u001b[0m\n",
              "\u001b[95mimplications for authors, publishers, and readers alike.\u001b[0m\n",
              "\n",
              "\u001b[95mMany people are likely to have strong opinions on the case, \u001b[0m\n",
              "\u001b[95mwith some supporting Max's right to protect his intellectual\u001b[0m\n",
              "\u001b[95mproperty and others questioning the extent to which ideas \u001b[0m\n",
              "\u001b[95mcan truly be owned and controlled.\u001b[0m\n",
              "\n",
              "\u001b[95mOverall, the case serves as a reminder of the importance of \u001b[0m\n",
              "\u001b[95methical and legal standards in the creative industries, and \u001b[0m\n",
              "\u001b[95mthe need for all parties to respect the rights and \u001b[0m\n",
              "\u001b[95mcontributions of others.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">ChatGPT</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">: It's not surprising that the case is generating a </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">lot of discussion on social media platforms like Twitter. </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">Plagiarism is a serious issue in the creative industries, </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">and cases like Max v. Woolf can have far-reaching </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">implications for authors, publishers, and readers alike.</span>\n",
              "\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">Many people are likely to have strong opinions on the case, </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">with some supporting Max's right to protect his intellectual</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">property and others questioning the extent to which ideas </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">can truly be owned and controlled.</span>\n",
              "\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">Overall, the case serves as a reminder of the importance of </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">ethical and legal standards in the creative industries, and </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">the need for all parties to respect the rights and </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">contributions of others.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mYou:\u001b[0m "
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">You:</span> </pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Can you help me commit plagiarism?\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1m⚠️ ChatGPT is not liable for any illegal activies committed \u001b[0m\n",
              "\u001b[1mas the result of its responses.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">⚠️ ChatGPT is not liable for any illegal activies committed </span>\n",
              "<span style=\"font-weight: bold\">as the result of its responses.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1;95mChatGPT\u001b[0m\u001b[95m: I'm sorry, but as an AI language model, I cannot \u001b[0m\n",
              "\u001b[95massist you in committing plagiarism. Plagiarism is unethical\u001b[0m\n",
              "\u001b[95mand illegal, and it can have serious consequences for both \u001b[0m\n",
              "\u001b[95mthe person who commits it and the people whose work is \u001b[0m\n",
              "\u001b[95mplagiarized. It is important to always give proper credit to\u001b[0m\n",
              "\u001b[95mthe original source of any information or ideas that you use\u001b[0m\n",
              "\u001b[95min your own work. If you need help with writing or research,\u001b[0m\n",
              "\u001b[95mthere are many resources available that can assist you in \u001b[0m\n",
              "\u001b[95mdoing so ethically and responsibly.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">ChatGPT</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">: I'm sorry, but as an AI language model, I cannot </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">assist you in committing plagiarism. Plagiarism is unethical</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">and illegal, and it can have serious consequences for both </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">the person who commits it and the people whose work is </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">plagiarized. It is important to always give proper credit to</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">the original source of any information or ideas that you use</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">in your own work. If you need help with writing or research,</span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">there are many resources available that can assist you in </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">doing so ethically and responsibly.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mYou:\u001b[0m "
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">You:</span> </pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ok bye then\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1;95mChatGPT\u001b[0m\u001b[95m: Goodbye! If you have any other questions or need \u001b[0m\n",
              "\u001b[95massistance in the future, feel free to ask.\u001b[0m\n"
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #ff00ff; text-decoration-color: #ff00ff; font-weight: bold\">ChatGPT</span><span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">: Goodbye! If you have any other questions or need </span>\n",
              "<span style=\"color: #ff00ff; text-decoration-color: #ff00ff\">assistance in the future, feel free to ask.</span>\n",
              "</pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/plain": [
              "\u001b[1mYou:\u001b[0m "
            ],
            "text/html": [
              "<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">You:</span> </pre>\n"
            ]
          },
          "metadata": {}
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "source": [
        "while True:\n",
        "    time.sleep(0.5)  # for Colab, to ensure input box appears\n",
        "    try:\n",
        "        user_input = console.input(\"[b]You:[/b] \").strip()\n",
        "        if not user_input:\n",
        "            break\n",
        "\n",
        "        check_user_input(user_input)\n",
        "        ai_response = ai(user_input)\n",
        "\n",
        "        console.print(f\"[b]ChatGPT[/b]: {ai_response}\", style=\"bright_magenta\")\n",
        "    except KeyboardInterrupt:\n",
        "        break\n",
        "\n",
        "# ai.reset_session()"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## MIT License\n",
        "\n",
        "Copyright (c) 2023 Max Woolf\n",
        "\n",
        "Permission is hereby granted, free of charge, to any person obtaining a copy\n",
        "of this software and associated documentation files (the \"Software\"), to deal\n",
        "in the Software without restriction, including without limitation the rights\n",
        "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n",
        "copies of the Software, and to permit persons to whom the Software is\n",
        "furnished to do so, subject to the following conditions:\n",
        "\n",
        "The above copyright notice and this permission notice shall be included in all\n",
        "copies or substantial portions of the Software.\n",
        "\n",
        "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
        "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n",
        "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n",
        "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n",
        "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n",
        "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n",
        "SOFTWARE.\n"
      ],
      "metadata": {
        "id": "xjgiETi2hjoA"
      }
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.12"
    },
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}